home *** CD-ROM | disk | FTP | other *** search
/ Business Shareware / Business Shareware.iso / start / wordproc / me_cd25 / cmode.mut < prev    next >
Encoding:
Text File  |  1992-11-09  |  12.8 KB  |  435 lines

  1. ;; cmode.mut : an electric C mode
  2.  
  3. ;;   Electric C mode is designed to help keep your C code formatted "as you
  4. ;; code".  You don't have to remember anything special - as you type, what
  5. ;; you type is looked at and may trigger certain actions.  This is a
  6. ;; minimalist C mode ment to enable you to keep your C code formatted in a
  7. ;; consistant manner.  The only extensive help is for comments.
  8.  
  9. ;; Characters that trigger formatting:
  10. ;;  "{": When a "{" is pressed, one of the following will happen:
  11. ;;     - If the space bar is pressed, "{ }" is generated and the cursor is
  12. ;;     put between the braces.
  13. ;;     - If Enter is pressed:
  14. ;;       And the rest of the line is blank, you will get something like:
  15. ;;        if (a) {        or  if (a)
  16. ;;          cursor        {
  17. ;;        }              cursor
  18. ;;                }
  19. ;;       depending on where the "{" was.  The cursor is indented by the
  20. ;;       amount specified by "INDENT-LEVEL".
  21. ;;     If the rest of the line was not blank, a newline-and-indent is
  22. ;;       done and the text after the { is indented.
  23. ;;       For example:
  24. ;;        if (a) foo(): if a "{ Enter" is done before the foo()
  25. ;;        you will get:
  26. ;;        if (a) {
  27. ;;          foo()
  28. ;;     - Otherwise, a "{" is inserted.
  29. ;;  Backspace:  Behaves like backspacing over spaces even when backspacing
  30. ;;    over tabs.
  31. ;;  Newline (control-J):  Used to give some white space after a variable
  32. ;;    declaration block.  The cursor is left at the same column as the start
  33. ;;    of the declarations.
  34. ;;    int j;    => int j;
  35. ;;           blank line
  36. ;;           cursor
  37. ;;  "/": Comment assistance.
  38. ;;     - If "*" is pressed and the rest of the line is blank and there is
  39. ;;     text to the left of the "/", "/* */" is generated and the cursor
  40. ;;     is put in the middle of the comment.  This is for end of line
  41. ;;     comments like:  if (a) foobar();    /* comment */
  42. ;;     - If "*" is pressed and the entire line is blank, block comment mode
  43. ;;     is entered.  In this mode, your comment will autowrap at the
  44. ;;     COMMENT-WRAP-COLUMN.  When you hit Enter or autowrap, stars are
  45. ;;     put in the proper place, whitespace is added to match the
  46. ;;     previous comment line.  If you press Enter "/", comment mode will
  47. ;;     terminate.  "*/" or "*" blanks "/" will also terminate comment
  48. ;;     mode.  If you want to get out of comment mode without using the
  49. ;;     above, press M-; or execute "nocomment".
  50. ;;     Examples:
  51. ;;        /*
  52. ;;             * Comment
  53. ;;         *   Indented a bit
  54. ;;         *   Next line follows the indent.
  55. ;;         */
  56. ;;        /*
  57. ;;        ** Another comment style
  58. ;;        */
  59. ;;     - Otherwise, a "/" is inserted.
  60. ;;  Meta-;
  61. ;;    If in block comment mode, turn off comment mode.
  62. ;;    If the cursor is on a line that is part of a block comment, start up
  63. ;;      block comment mode.  This is very handy for adding to an existing
  64. ;;      block comment.
  65. ;;  Meta-J:  Format a C block comment.
  66. ;;    If you munge a block comment and want to set it right, use this.
  67. ;;    This formats all the lines between the dot and mark inclusive.
  68. ;;    Put the region around the comment (or the part of the comment you want
  69. ;;      to format) and press M-J.  The comment is commented in the format of
  70. ;;      comment mode.
  71. ;;    Notes:
  72. ;;    To make sure that line breaks are preserved, insert blank lines at
  73. ;;      the breaks.  The blank lines will be deleted after the comment
  74. ;;      is formatted.
  75. ;;    To change the indent level of the block, indent the first line of
  76. ;;      the region to where you want.
  77. ;;  Control-U Meta-J: Format a C boxed comment.
  78. ;;    Same as format block comment except the comment is boxed:
  79. ;;    /********************************
  80. ;;     *   Comment            *
  81. ;;     ********************************/
  82. ;;  You can convert between boxed and block comments by just reformatting.
  83.  
  84. ;; C Durland    Public Domain
  85.  
  86.  
  87. (const
  88.   INDENT-LEVEL        2    ;; spaces to indent a {} block
  89.   COMMENT-WRAP-COLUMN  76    ;; where to word wrap in comment mode
  90.   TAB-SIZE        0    ;; 0 means use tabs else n spaces for each tab
  91.  
  92.   C-STARS " *"        ;; comment body stars: " *"  or "**".
  93.   COMET   " */"        ;; comment end stars:  " */" or "*/".
  94.  
  95.     ;; number of blank lines before and after text in boxed comment
  96.   BOXED-COMMENT-SPACE        1    ;; blank lines between box and text
  97.   BOXED-COMMENT-TRAILING-BLANKS 1    ;; blanks between text and *
  98.   BOXED-COMMENT-EDGE-STARS    "*"    ;; right edge stars: "*" or "**"
  99.  
  100.   ENTER-KEY-ACTION "newline-and-indent"    ;; newline-and-indent or newline
  101. )
  102.  
  103. (int
  104.   indent-level comment-wrap-column
  105.   boxed-comment-space boxed-comment-trailing-blanks
  106. )
  107. (string c-stars comet boxed-comment-edge-stars enter-key-action)
  108.  
  109. (include me2.h)
  110.  
  111. (defun
  112.   c-mode    ; set up electric C mode
  113.   {
  114.     (clear-modes)
  115.  
  116.     (bind-local-key ENTER-KEY-ACTION    "C-m")
  117.     (bind-local-key "C-mode-{"        "{")
  118.     (bind-local-key "after-declare"    "C-j")
  119.     (bind-local-key "Dr.commento"    "/")
  120.     (bind-local-key "BS-untabify"    "C-h")
  121.     (bind-local-key "format-C-comment"    "M-j")
  122.     (bind-local-key "Nurse-commento"    "M-;")
  123.  
  124.     (create-buffer-var NUMBER "comment-offset")
  125.  
  126.     (major-mode "C")
  127.  
  128.     (tab-stops TAB-SIZE)
  129.     (c-mode-etc INDENT-LEVEL COMMENT-WRAP-COLUMN C-STARS COMET)
  130.     (c-mode-boxed BOXED-COMMENT-SPACE BOXED-COMMENT-TRAILING-BLANKS
  131.           BOXED-COMMENT-EDGE-STARS)
  132.  
  133.     (if (pgm-exists "c-mode-hook") (floc "c-mode-hook"()))
  134.  
  135.     (enter-key-action (key-bound-to "C-m"))
  136.   }
  137.   c-mode-etc (int indent comment-wrap) (string stars comets)
  138.   {
  139.     (indent-level indent)
  140.     (comment-wrap-column comment-wrap)
  141.     (c-stars stars)
  142.     (comet comets)
  143.   }
  144.   c-mode-boxed (int comment-space trailing-blanks) (string edge-stars)
  145.   {
  146.     (boxed-comment-space        comment-space)
  147.     (boxed-comment-trailing-blanks    trailing-blanks)
  148.     (boxed-comment-edge-stars        edge-stars)
  149.   }
  150. )
  151.  
  152. (include bs_untab.mut)
  153. (include block.mut)
  154.  
  155. (defun
  156.   "C-mode-{"    ; handle {
  157.   {
  158.     (int key n)
  159.  
  160.     (insert-text "{")(update)
  161.     (switch (key (get-key))
  162.       Space-bar        ;  try for { . } else just insert a blank
  163.     {
  164.       (if (looking-at '\ *$')    ; only whitespace 'til end of line
  165.         { (insert-text "  }")(previous-character)(previous-character) }
  166.         (insert-text " ")
  167.       )
  168.     }
  169.       Enter-key
  170.         {
  171.       (newline-and-indent)(n (current-column))
  172.       (if (looking-at '\ *$')    ; white space to end of line
  173.       {
  174.         (insert-text "}")
  175.         (beginning-of-line)(open-line)
  176.       })
  177.       (to-col (+ n indent-level))
  178.     }
  179.       default (exe-key key)
  180.     )
  181.   }
  182.   after-declare        ; properly indent after a var declare
  183.   {
  184.     (newline-and-indent)(beginning-of-line)(open-line)
  185.     (forward-line 1)(end-of-line)
  186.   }
  187. )
  188.  
  189. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  190. ;;;;;;;;;;;;; Comment mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  191. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  192.  
  193. (defun
  194.   Dr.commento        ; handle "/" & start up comment mode if need be
  195.   {
  196.     (int key col)
  197.  
  198.     (insert-text "/")(update)
  199.     ;; Check to see if starting a comment.  No "*" => no comment
  200.     (if (!= (key (get-key)) 0x2A) { (exe-key key)(done) } )
  201.     ;; check to see if this is a comment block
  202.     (insert-text "*")
  203.     (col (current-column))(beginning-of-line)
  204.     (if (not (looking-at '\ */\*\ *$'))    ; ws/*ws
  205.     {        ; its not a comment block - give them "/*   */"
  206.       (current-column col)
  207.       (if (looking-at '\ *$')    ; only if at end of line
  208.     { (insert-text "  */")(arg-prefix 3)(previous-character) } )
  209.       (done)
  210.     })
  211.     (current-column col)    ;; move back to where we started
  212.     (insert-text " ")        ;; make it look like "/* "
  213.     (start-block-comment col)
  214.   }
  215.   Nurse-commento    ;; Reenter block comment mode
  216.   {
  217.     (int col)
  218.  
  219.     (col (current-column))(beginning-of-line)
  220.     (if (or
  221.       (looking-at '\ *\*')        ;; [ws]*
  222.       (looking-at '\ */\*'))    ;; [ws]/*
  223.       {
  224.     (search-forward '*')
  225.     (start-block-comment (current-column))
  226.     (if (looking-at '.*\*/')        ;; [stuff]*/
  227.     {
  228.       (msg 'Notice that trailing "*/"!')
  229.     })
  230.       }
  231.       {
  232.     (msg "Not in a block comment!")
  233.       })
  234.     (current-column col)
  235.   }
  236.   start-block-comment (int col)    HIDDEN        ;; turn on block comment mode
  237.   {
  238.     (buffer-var "comment-offset" (- col 2))
  239.     (word-wrap comment-wrap-column)
  240.  
  241.     (bind-local-key "Dr.CR"    "C-m")
  242.     (bind-local-key "C-mode-/"    "/")
  243.     (bind-local-key "nocomment"    "M-;")
  244.     (minor-mode "Dr. Commento")
  245.   }
  246.   nocomment                ;; Turn off comment mode
  247.   {
  248.     (bind-local-key enter-key-action    "C-m")
  249.     (bind-local-key "Dr.commento"    "/")
  250.     (bind-local-key "Nurse-commento"    "M-;")
  251.  
  252.     (minor-mode "")
  253.     (word-wrap 0)
  254.   }
  255.   Dr.CR                ;; handle Enter while in comment mode
  256.   {
  257.     (open-line)(beginning-of-line)
  258.         ;; Note: save ws after *'s so can preserve indent.
  259.     (if (looking-at '\ *.\ *\*+\(\ *\)') ; [ws]/*[ws] | ws*[*...][ws]
  260.       {
  261.     (forward-line 1)
  262.     (to-col (buffer-var "comment-offset"))
  263.     (insert-text c-stars (get-matched '\1'))    ;; match prev indent
  264.       }
  265.       {        ;; probably should handle this case better
  266.     (forward-line 1)
  267.     (msg "Your not in a comment block!")
  268.       })
  269.   }
  270.   C-mode-/            ;; handle "/" in comment mode
  271.   {
  272.     (int col)
  273.  
  274.     (col (current-column))
  275.     (previous-character)
  276.     (if (looking-at '\*')        ;; "*/" => ending comment
  277.       { (nocomment)(goto ick) })
  278.     (beginning-of-line)
  279.     (if (looking-at '\ *\*+\ *$')    ;; [ws]*[*...][ws]/
  280.     {
  281.       (current-column (buffer-var "comment-offset"))
  282.       (cut-line)
  283.       (insert-text comet)
  284.       (nocomment)
  285.       (done)
  286.     })
  287.   (label ick)
  288.     (current-column col)(insert-text "/")
  289.   }
  290. )
  291.  
  292. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  293. ;;;;;;;; Format block comment ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  294. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  295.  
  296. (defun
  297.   add-stars (int n) HIDDEN
  298.   {
  299.     (int j)
  300.  
  301.     (j (+ n 1))
  302.     (while (!= 0 (-= j 1)) (insert-text "*"))
  303.   }
  304.   format-C-comment
  305.   {
  306.     (bool start-comment end-comment boxed-comment)
  307.     (int offset j)
  308.     (int code-buffer scrbuf bag-id)
  309.  
  310.     (boxed-comment (arg-flag))
  311.  
  312.     (start-comment (end-comment FALSE))
  313.  
  314.     (code-buffer (current-buffer))
  315.     (delete-region-as-block)
  316.  
  317.     (current-buffer (scrbuf (create-buffer scratch-buffer)))
  318.  
  319.     (insert-bag CUT-BUFFER)
  320.  
  321.     (beginning-of-buffer)
  322.     (if (re-search-forward '^\ */\*')    ; ^[ws]/*
  323.       {
  324.     (start-comment TRUE)
  325.     (offset (- (current-column) 2))
  326.     (beginning-of-line)
  327.     (re-search-replace '^\ */\*+' "")  ; get rid of ^[ws]/*[*...]
  328.       }
  329.       {
  330.     (if (search-forward c-stars)
  331.       (offset (- (current-column) 2))
  332.       {
  333.         ; else get the block offset from left margin
  334.         (beginning-of-line)
  335.         (while (is-space) (next-character))
  336.         (offset (current-column))
  337.       }
  338.     )
  339.       }
  340.     )
  341.  
  342.     (beginning-of-buffer)
  343.     (if (re-search-forward '\*/\ *$')    ; */[ws]$
  344.     {
  345.       (end-comment TRUE)
  346.       (beginning-of-line)
  347.       (re-search-replace '\ *\*+/\ *$' "")    ; get rid of [ws]*[*...]/[ws]$
  348.     })
  349.     (beginning-of-buffer)
  350.     (re-search-replace '^\ *\*+' "")    ; get rid of [white-space]*[*...]
  351.  
  352.     (beginning-of-buffer)
  353.     (re-search-replace '\ *\*+$' "")    ; get rid of [white-space]*[*...]$
  354.  
  355.     (msg "Formatting comment ...")
  356.     (beginning-of-buffer)
  357.     (adjust-lines
  358.       10000
  359.       (- comment-wrap-column offset 1
  360.     (if boxed-comment
  361.       (+ (length-of boxed-comment-edge-stars)
  362.          boxed-comment-trailing-blanks)
  363.       0
  364.     ))
  365.       FALSE
  366.     )
  367.     (beginning-of-buffer)
  368.     
  369.     ; put /*, * and */ in front of text
  370.     (if start-comment
  371.     {
  372.       (to-col offset)(insert-text '/*')
  373.       (if boxed-comment
  374.       {
  375.     (if (not (looking-at '\ *$')) (open-line))
  376.     (add-stars (- comment-wrap-column (current-column)))
  377.     (insert-text boxed-comment-edge-stars)
  378.     (j boxed-comment-space)
  379.     (while (<= 0 (-= j 1))
  380.     {
  381.       (newline-and-indent)(insert-text c-stars)
  382.       (to-col comment-wrap-column)(insert-text boxed-comment-edge-stars)
  383.     })
  384.       })
  385.       (forward-line 1)
  386.     })
  387.     (while (not (EoB))
  388.     {
  389.       (if (looking-at '^$')
  390.         { (arg-prefix 1)(cut-line)(continue) }        ; remove blank lines
  391.     {        ; else prepend *
  392.       (to-col offset)(insert-text c-stars)
  393.       (if boxed-comment
  394.           {
  395.         (end-of-line) (to-col comment-wrap-column)
  396.         (insert-text boxed-comment-edge-stars)
  397.       })
  398.     }
  399.       )
  400.       (forward-line 1)
  401.     })
  402.     (if end-comment
  403.     {
  404.       (to-col offset)
  405.       (if boxed-comment
  406.     {
  407.       (j boxed-comment-space)
  408.       (while (<= 0 (-= j 1))
  409.       {
  410.         (insert-text c-stars)
  411.         (to-col comment-wrap-column)(insert-text boxed-comment-edge-stars)
  412.         (newline)(to-col offset)
  413.       })
  414.       (insert-text c-stars)
  415.       (add-stars (- comment-wrap-column (current-column)))
  416.       (insert-text boxed-comment-edge-stars "/")
  417.     }
  418.     (insert-text comet)
  419.       )
  420.     })
  421.  
  422.     ;; replace comment
  423.     (beginning-of-buffer)(set-mark)(end-of-buffer)
  424.     (append-to-bag (bag-id (create-bag)) APPEND-REGION)
  425.  
  426.     (msg "Comment formatted.")
  427.  
  428.     (current-buffer code-buffer)
  429.     (insert-bag bag-id)
  430.  
  431.     ; clean up
  432.     (free-buffer scrbuf)(free-bag bag-id)
  433.   }
  434. )
  435.